<?php

namespace app\api\controller;

use app\admin\model\AskForLeave;
use app\admin\model\ClassAddress;
use app\admin\model\ClockIn;
use app\admin\model\Club;
use app\admin\model\ClubDtl;
use app\admin\model\Invoice;
use app\admin\model\Notice;
use app\admin\model\Order;
use app\admin\model\StopClassReason;
use app\admin\model\TeacherClass;
use app\admin\model\TeacherClassDtl;
use app\admin\model\TeacherCourseDisplay;
use app\admin\model\TeacherSubscribe;
use app\common\controller\Api;
use think\Config;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use OSS\OssClient;
use OSS\Core\OssException;

/**
 * 课程接口
 */
class ClassApi extends Api
{
    protected $noNeedLogin = [];
    protected $noNeedRight = '*';

    public function _initialize()
    {
        parent::_initialize();
    }

    //课程列表
    public function class_list(){
        $params = $this->request->param();
        if(!isset($params['page'])||!$params['page']){
            $params['page'] = 1;
        }
        if(!isset($params['page_size'])||!$params['page_size']){
            $params['page_size'] = 10;
        }

        $user = $this->auth->getUser();
        if(!$user){
            $this->error('未获取到用户信息');
        }
        if($user['identity_type'] == '教师'){
            $query = TeacherClass::where(['teacher_id'=>$user['id'],'is_t_del'=>0]);
        }elseif($user['identity_type'] == '校方'){
            $query = TeacherClass::where(['user_id'=>$user['id'],'is_s_del'=>0]);
        }else{
            $data['list'] = [];
            $data['count'] = 0;
            $this->success('课程列表',$data);
        }
        $query->with(['users','teachers']);
        if(isset($params['status'])&&$params['status']){
            $query->where(['status'=>$params['status']]);
        }
        $query = $query->order('id','desc')->paginate($params['page_size']);

        $list = $query->getCollection();
        $arr_id = [];
        $arr_address_id = [];
        foreach ($list as $k=>$v) {
            $arr_id[] = $v['id'];
            $arr_address_id[] = $v['address_id'];
        }
        $dtl = TeacherClassDtl::whereIn('teacher_class_id',$arr_id)->select();
        $arr_dtl = [];
        foreach ($dtl as $k=>$v){
            if(isset($arr_dtl[$v['id']])&&$arr_dtl[$v['id']]){
                $week_date = '/'.$v['week_date'];
                $arr_dtl[$v['id']] .= $week_date;
            }else{
                $arr_dtl[$v['id']] = $v['week_date'];
            }
        }

        $address = ClassAddress::whereIn('id',$arr_address_id)->select();
        $address_dtl = [];
        foreach ($address as $k=>$v){
            $address_dtl[$v['id']] = $v['school'].'-'.$v['detail'];
        }

        $arr = [];
        if($user['identity_type'] == '校方'){
            foreach ($list as $k=>$v) {
                $arr[$k]['id'] = $v['id'];
                $arr[$k]['name'] = isset($v['teachers']['nickname']) ? $v['teachers']['nickname'] : '';
                $arr[$k]['club_two_name'] = $v['club_two_name'];
                $arr[$k]['avatar'] = isset($v['teachers']['avatar']) ? $v['teachers']['avatar'] : '';
                $arr[$k]['subscribe_date'] = isset($arr_dtl[$v['id']]) ? $arr_dtl[$v['id']] : '';
                $arr[$k]['schedule'] = $v['completed_class_num'].'/'.$v['class_num_all'];
                switch ($v['status']){
                    case 1:
                        $arr[$k]['status'] = '进行中';
                        break;
                    case 2:
                        $arr[$k]['status'] = '已完成';
                        break;
                    case 3:
                        $arr[$k]['status'] = '已中止';
                        break;
                    default:
                        $arr[$k]['status'] = '';
                        break;
                }
                $arr[$k]['start_date'] = $v['start_date'];
                $arr[$k]['del_reason'] = $v['del_reason'];
            }
        }elseif($user['identity_type'] == '教师') {
            foreach ($list as $k=>$v) {
                $arr[$k]['id'] = $v['id'];
                $arr[$k]['name'] = isset($v['users']['nickname']) ? $v['users']['nickname'] : '';
                $arr[$k]['address_name'] = isset($address_dtl[$v['address_id']]) ? $address_dtl[$v['address_id']] : '';
                $arr[$k]['avatar'] = isset($v['users']['avatar']) ? $v['users']['avatar'] : '';
                $arr[$k]['subscribe_date'] = isset($arr_dtl[$v['id']]) ? $arr_dtl[$v['id']] : '';
                $arr[$k]['schedule'] = $v['completed_class_num'].'/'.$v['class_num_all'];
                switch ($v['status']){
                    case 1:
                        $arr[$k]['status'] = '进行中';
                        break;
                    case 2:
                        $arr[$k]['status'] = '已完成';
                        break;
                    case 3:
                        $arr[$k]['status'] = '已中止';
                        break;
                    default:
                        $arr[$k]['status'] = '';
                        break;
                }
                $arr[$k]['start_date'] = $v['start_date'];
                $arr[$k]['del_reason'] = $v['del_reason'];
            }
        }

        $count = $query->total();
        $data['list'] = $arr;
        $data['count'] = $count;

        $this->success('课程列表',$data);
    }

    //课程详情
    public function class_detail(){
        $params = $this->request->param();
        if(!isset($params['id'])||!$params['id']){
            $this->error('课程id必传');
        }
        $user = $this->auth->getUser();
        if(!$user){
            $this->error('未获取到用户信息');
        }

        $find = TeacherClass::where(['id'=>$params['id']])->with(['dtls'])->find();
        if(!$find){
            $this->error('课程不存在');
        }
        $teacher_info = \app\admin\model\IdentityInfo::where(['user_id'=>$find['teacher_id'],'identity_type'=>'教师'])->find();
        if(!$teacher_info){
            $this->error('教师身份不存在');
        }
        if($user['identity_type'] == '校方'){
            $teacher_user = \app\admin\model\User::where(['id'=>$find['teacher_id']])->find();
            $avatar = isset($teacher_user['avatar']) ? $teacher_user['avatar'] : '';
            $name = isset($teacher_user['nickname']) ? $teacher_user['nickname'] : '';
            $school = '';
        }elseif($user['identity_type'] == '教师'){
            $teacher_user = \app\admin\model\User::where(['id'=>$find['user_id']])->find();
            $avatar = isset($teacher_user['avatar']) ? $teacher_user['avatar'] : '';
            $name = isset($teacher_user['nickname']) ? $teacher_user['nickname'] : '';
            $school_info = \app\admin\model\IdentityInfo::where(['user_id'=>$find['user_id']])->find();
            $school = isset($school_info['school']) ? $school_info['school'] : '';
        }else{
            $arr = [];
            $this->success('课程详情',$arr);
            return false;
        }
        $td = \app\admin\model\TeacherDetail::where(['id'=>$find['teacher_detail_id']])->find();
        if(isset($td['course_duration'])&&$td['course_duration']){
            //当教师课程配置了课程时间 则赋值课程时间
            $duration = $td['course_duration'];
        }else{
            //如果没有配置，则取公共课程时间
            $defaultDuration = Config::get('course.default_course_duration', '');
            $duration = $defaultDuration;
        }
        $arr = [];
        $arr['id'] = $params['id'];//名称
        $arr['name'] = $name;//名称
        $arr['school'] = $school;//学校名称
        $arr['avatar'] = $avatar;//头像
        $arr['user_id'] = $find['user_id'];//购买方id
        $arr['teacher_id'] = $find['teacher_id'];//教师的user_id
        $arr['teacher_detail_id'] = $find['teacher_detail_id'];//教师的身份课程id
        $arr['appointment_time_week'] = isset($teacher_info['appointment_time_week']) ? $teacher_info['appointment_time_week'] : '';//可约时间（周）
        $arr['appointment_time'] = isset($teacher_info['appointment_time']) ? $teacher_info['appointment_time'] : '';//可约时间（时）
        $arr['club_two_name'] = $find['club_two_name'];//社团名称
        $arr['schedule'] = $find['completed_class_num'].'/'.$find['class_num_all'];//课程进度
        $arr['start_date'] = $find['start_date'];//开始时间
        $arr['semester'] = $find['semester'];//学期
        $arr['class_num_all'] = $find['class_num_all'];//总课时
        $arr['class_period_num'] = ((int)$find['class_period']) ? (int)$find['class_period'] : '';//学期
        switch ($find['status']){
            case 1:
                $arr['status'] = '进行中';
                break;
            case 2:
                $arr['status'] = '已完成';
                break;
            case 3:
                $arr['status'] = '已中止';
                break;
            default:
                $arr['status'] = '';
                break;
        }
        $address = ClassAddress::where(['id'=>$find['address_id']])->find();
        if($address){
            $arr['address_name'] = $address['school'].'-'.$address['detail'];
        }else{
            $arr['address_name'] = '';
        }
        $arr['address_id'] = $find['address_id'];
        $arr['class_period'] = $find['class_period'];
        $arr['class_money'] = $find['money'];
        switch ($find['period_set']){
            case 1:
                $arr['period_set'] = '每周';
                break;
            case 2:
                $arr['period_set'] = '日期';
                break;
        }
        $dtl = [];

        $identity_info_model = new \app\admin\model\IdentityInfo();
        $week_list_name = $identity_info_model->getWeekNameList();

        $time_start = '';
        $clock_in = 0;
        foreach ($find['dtls'] as $k=>$v){
            $dtl[$k]['week_date'] = isset($week_list_name[$v['week_date']]) ? $week_list_name[$v['week_date']] : '';
            $dtl[$k]['week_date_name'] = $v['week_date'];
            $all_duration = precisionRestore($v['class_num'],$duration,'乘法');
            $time_start = $v['time_start'];
            $time_end = $this->safeTimeAdd($time_start, $all_duration) ?: '';
            $dtl[$k]['time_start'] = $v['time_start'].' - '.$time_end;
            $dtl[$k]['class_num'] = $v['class_num'];
            $dtl[$k]['status'] = $v['status'];
            switch ($v['status']){
                case 1:
                    $dtl[$k]['status_name'] = '未开始';
                    break;
                case 2:
                    $dtl[$k]['status_name'] = '已完成';
                    break;
                default:
                    $dtl[$k]['status_name'] = '';
                    break;
            }
            $subStr = "周";
            if (strstr($v['week_date'], $subStr)) {
                $start_time = getWeekDay(date('Y-m-d H:i:s'));
                if($v['week_date'] == $start_time&&date('Y-m-d')>=$find['start_date']){
                    //需要打卡
                    $clock_in++;
                }
            }else{
                $date_class = date('Y-m-d',strtotime($v['week_date']));
                if($date_class == date('Y-m-d')&&date('Y-m-d')>=$find['start_date']){
                    //需要打卡
                    $clock_in++;
                }
            }
        }
        $arr['time_start'] = $time_start;
        $arr['class_dtl'] = $dtl;
        $arr['score'] = $find['score'];//评分

        $afl = AskForLeave::where(['class_id'=>$params['id'],'status'=>2])->select();

        $asd = 0;
        $qj = [];
        foreach ($afl as $k=>$v){
            $date = date('Y-m-d',strtotime($v['make_up_classes_time']));
            $is_within = dateWithinThisWeek($date);
            if($is_within){
                //在本周内 显示数据 并查询是否已完成
                $qj[$asd]['week'] = dateWeek($date);

                $add_time = precisionRestore($v['class_num'],$duration,'乘法');
                $end_time = $this->safeTimeAdd($params['class_start_time'],$add_time);
                if(!$end_time){
                    $this->error('课程开始时间加上课时不可跨天');
                }
                if($end_time){
                    $qj[$asd]['date'] = $v['bk_time']. '-'.$end_time;
                }else{
                    $qj[$asd]['date'] = $v['bk_time'];
                }
                $qj[$asd]['status'] = $v['is_wc'];

                if($date == date('Y-m-d')){
                    //需要打卡
                    $clock_in++;
                }
            }
        }
        //减去已打卡的次数
        $ci_count = ClockIn::where(['class_id'=>$params['id'],'date'=>date('Y-m-d')])->count();
        $clock_in = precisionRestore($clock_in,$ci_count,'减法');
        if($clock_in<0){
            $clock_in = 0;
        }
        $arr['ask_for_leave'] = $qj;//请假数据

        $arr['clock_in_type'] = '上课打卡';//需要打卡的次数
        $ci_new = ClockIn::where(['class_id'=>$params['id'],'date'=>date('Y-m-d')])->order('id','desc')->find();
        if(isset($ci_new['is_sk'])&&$ci_new['is_sk']==1){
            $arr['clock_in_type'] = '下课打卡';//需要打卡的次数
            $clock_in++;
        }
        $arr['clock_in_num'] = $clock_in;//需要打卡的次数
        $arr['del_reason'] = $find['del_reason'];//购买方id
        $arr['teacher_phone'] = isset($teacher_info['phone']) ? $teacher_info['phone'] : '';//教师电话

        $dtl_rl = TeacherClassDtl::where(['teacher_class_id'=>$params['id']])->order('date','asc')->select();
        $rl = [];
        foreach ($dtl_rl as $k=>$v){
            $rl[$k]['date'] = $v['date'];
            $rl[$k]['status'] = $v['status'];
            if($v['date']<date('Y-m-d')){
                if($v['status'] == 1){
                    $rl[$k]['status'] = 4;
                }
            }
        }

        $arr['rl_data'] = $rl;
        $this->success('课程详情',$arr);
    }

    //更新课程下拉
    public function up_class_pull(){
        $params = $this->request->param();
        if(!isset($params['class_id'])||!$params['class_id']){
            $this->error('课程id必传');
        }
        $user = $this->auth->getUser();
        if(!isset($user['id'])||!$user['id']){
            $this->error('当前登录用户不存在');
        }
        $data = [];
        if($user['identity_type'] == '校方'){
            $class = TeacherClass::where(['id'=>$params['class_id']])->find();
            $week_arr = TeacherSubscribe::where(['teacher_id'=>$class['teacher_id']])->where('1=1 and (class_id = 0 or class_id = '.$params['class_id'].')')->column('week');
            $arr = [];
            foreach ($week_arr as $k=>$v){
                $arr[] = (int)$v;
            }
            sort($arr);
            $data['week'] = $arr;
            $identity_info_model = new \app\admin\model\IdentityInfo();
            $getWeekList = $identity_info_model->getWeekList();
            $week_name = [];
            foreach ($arr as $k=>$v){
                $week_name[$v] = isset($getWeekList[$v]) ? $getWeekList[$v] : '';
            }
            $data['week_name'] = $week_name;
        }
        $this->success('更新课程下拉',$data);
    }

    //更新课程详情(废弃)
    public function up_class_detail_new(){
        $params = $this->request->param();
        if(!isset($params['id'])||!$params['id']){
            $this->error('课程id必传');
        }
        $user = $this->auth->getUser();
        if(!$user){
            $this->error('未获取到用户信息');
        }
        if($user['identity_type'] != '校方'){
            $this->error('当前身份不可修改课程信息');
        }
        $class = TeacherClass::where(['id'=>$params['id']])->with(['dtls'])->find();
        if(isset($params['address_id'])&&$params['address_id']){
            $address_id = $params['address_id'];
        }
        if($class['status']==3){
            $this->error('课程已中止，无法修改');
        }
        $identity_info = \app\admin\model\IdentityInfo::where(['user_id'=>$class['teacher_id'],'identity_type'=>'教师'])->with(['clubDtlS'])->find();
        if(!$identity_info){
            $this->error('教师不存在');
        }
        $time = explode('-',$identity_info['appointment_time']);

        $week_pd = date('N');
        $date = date('H:i:s');
        //确认是周末才可以改
        if($week_pd == 7&&$date>'23:00:00'){
            $this->error('周日23点之后为更新进度状态时间，不可修改状态，请于0点后尝试');
        }
        $ts = TeacherSubscribe::where(['teacher_id'=>$class['teacher_id']])->where('1=1 and (class_id = 0 or class_id='.$params['id'].')')->select();
        $week_arr = [];
        foreach ($ts as $k=>$v){
            $week_arr[] = $v['week'];
        }
//        $week = explode(',',$identity_info['appointment_time_week']);
        $identity_info_model = new \app\admin\model\IdentityInfo();
        $week_list_name = $identity_info_model->getWeekNameList();
//        $week_arr = [];
//        foreach ($week as $k=>$v){
//            $key = isset($week_list_name[$v]) ? $week_list_name[$v] : '';
//            $week_arr[$k] = $key;
//        }

        $dtl_status = [];
        $old_week = [];
        foreach ($class['dtls'] as $k=>$v){
            $dtl_status[$week_list_name[$v['week_date']]] = $v['status'];
            $old_week[] = $week_list_name[$v['week_date']];
        }
        $jian_num = 0;
        $jia_num = 0;
        $all_class_num = 0;
        $is_kc = 0;
        if(isset($params['dtl'])&&$params['dtl']){
            if($class['period_set'] == 2) {
                //短期
                $this->error('短期不可修改课程安排');
            }
            if(is_array($params['dtl'])){
                $dtl = $params['dtl'];
            }else{
                //php中参数有双引号 会自动转换
                $params['dtl'] = htmlspecialchars_decode($params['dtl'], ENT_QUOTES);
                $dtl = json_decode($params['dtl'],true);
            }
            $dtl_arr = [];
            $arr_week = [];
            foreach ($dtl as $k=>$v){
                if(!isset($v['week_date'])||!$v['week_date']){
                    $this->error('日期或周必传');
                }
                $arr_week[$k] = $v['week_date'];
                if(!isset($v['time_start'])||!$v['time_start']){
                    $this->error('开始时间必传');
                }
                if(!isset($v['class_num'])||!$v['class_num']){
                    $this->error('课时必传');
                }
                if(!isset($v['status'])||!$v['status']){
                    $this->error('状态必传');
                }


                if(isset($dtl_status[$v['week_date']])&&$dtl_status[$v['week_date']]){
                    if($dtl_status[$v['week_date']] == 2 &&$v['status'] == 1){
                        //修改状态为未开始 进度减1
                        $jian_num = precisionRestore($jian_num,$v['class_num'],'减法');
                    }
                    if($dtl_status[$v['week_date']] == 1 &&$v['status'] == 2){
                        //修改状态为已完成 进度加1
                        $jia_num = precisionRestore($jia_num,$v['class_num'],'加法');
                    }
                }
                $weekday = $v['week_date'];//长期默认周 传过来的是数字
                //判断日期是否在可约范围内，判断上课时间，判断课时
                if($class['period_set'] == 2){
                    //短期
                    $inputDate = $v['week_date'];

                    $weekday = date('N', strtotime($inputDate));
                }

                if (!in_array($weekday, $week_arr)) {
                    $this->error('周'.TeacherClassDtl::numberToChinese($weekday).'不在可约时间');
                }
                if($v['class_num']>6){
                    $this->error('单次上课最大6课时');
                }
                if(isset($time[0])&&$time[0]&&isset($time[1])&&$time[1]){
                    $add_time = precisionRestore($v['class_num'],'40','乘法');//..
                    $end_time = $this->safeTimeAdd($v['time_start'],$add_time);
                    if(!$end_time){
                        $this->error('课程开始时间加上课时不可跨天');
                    }
                    $result = $this->isTimeBetween($v['time_start'], $time[0], $time[1]);
                    if($result == false){
                        $this->error('课程开始时间不在服务时间内');
                    }
                    $result = $this->isTimeBetween($end_time, $time[0], $time[1]);
                    if($result == false){
                        $this->error('课程结束时间不在服务时间内');
                    }
                }
                $dtl_arr[$k]['teacher_class_id'] = $params['id'];//课程id
                if($class['period_set'] == 1){
                    $week_date = '周'.TeacherClassDtl::numberToChinese($weekday);
                }else{
                    $week_date = $v['week_date'];
                }
                $dtl_arr[$k]['week_date'] = $week_date;//日/周
                $dtl_arr[$k]['time_start'] = $v['time_start'];//开始时间
                $dtl_arr[$k]['class_num'] = $v['class_num'];//课时
                $dtl_arr[$k]['cycle'] = $class['period_set'];//周期 1每周 2日期
                $dtl_arr[$k]['status'] = $v['status'];//状态 1未开始 2已完成
                $all_class_num = precisionRestore($v['class_num'],$all_class_num,'加法');
            }
            $hasDuplicate = count($arr_week) !== count(array_unique($arr_week));
            if($hasDuplicate == true){
                $this->error('不可设置相同的周');
            }
            $count = TeacherSubscribe::where(['teacher_id'=>$class['teacher_id']])->where('class_id >0 and class_id !='.$class['id'])->whereIn('week',array_unique($arr_week))->count();
            if($count>0){
                $this->error('存在不可配置的可约时间');
            }
            $sub = TeacherSubscribe::up_class_subscribe(array_unique($arr_week),$class['teacher_id'],$params['id'],$old_week);
            if($sub['code'] == 0){
                $this->error($sub['msg']);
            }
            TeacherClassDtl::where(['teacher_class_id'=>$params['id']])->delete();
            if(count($dtl_arr)){
                TeacherClassDtl::insertAll($dtl_arr);
            }
            $class_num_bg = precisionRestore($jia_num,$jian_num,'减法');
            $completed_class_num = precisionRestore($class['completed_class_num'],$class_num_bg,'加法');
            $class_num_all = (int)$class['class_num_all'];
            $all_class_num = (int)$all_class_num;
            if($all_class_num&&$class_num_all){
                $class_period = ceil($class_num_all / $all_class_num);
            }else{
                $class_period = '暂无计划';
            }
            TeacherClass::where(['id'=>$params['id']])->update(['class_period'=>$class_period.'周','completed_class_num'=>$completed_class_num]);
            //完成进度
            TeacherClassDtl::jd_send_notice($params['id']);
            //发送通知 告知教师 修改了课程安排
            $is_kc = 1;
        }
        $is_dz = 0;
        if(isset($address_id)&&$address_id){
            if($class['address_id']!=$address_id){
                //发送通知 告知教师 修改了上课地点
                $is_dz = 1;
                TeacherClass::where(['id'=>$params['id']])->update(['address_id'=>$address_id]);
            }
        }
        $school_info = \app\admin\model\IdentityInfo::where(['user_id'=>$class['user_id'],'identity_type'=>'校方'])->find();
        $content = '';
        if($is_kc == 1){
            $content = $school_info['school'].'-'.$school_info['name'].' 修改了您的课程安排，请前往课程表查看';
        }
        if($is_dz == 1){
            $content = $school_info['school'].'-'.$school_info['name'].' 修改了您的上课地址，请前往课程表查看';
        }
        if($is_kc == 1 && $is_dz == 1){
            $content = $school_info['school'].'-'.$school_info['name'].' 修改了您的课程安排和上课地址，请前往课程表查看';
        }
        //给教师发通知 告知有人买课了
        $send_add_notice = [];
        $send_add_notice['title'] = '课程安排变更';//标题
        $send_add_notice['content'] = $content;//内容
        $send_add_notice['need_confirm'] = 2;//是否需要确认 1是 2否
        $send_add_notice['jump'] = '课程详情';//跳转地址
        $send_add_notice['teacher_class_id'] = $params['id'];//课程id
        $send_add_notice['teacher_class_dtl_id'] = 0;//课程安排id
        $send_add_notice['send_user_id'] = $class['user_id'];//发送人id
        $send_add_notice['get_user_id'] = $class['teacher_id'];//接收人id
        $send_add_notice['identity_type'] = '教师';//接收人身份
        $send_add_notice['addtime'] = date('Y-m-d H:i:s');//添加时间
        $send_add_notice['is_read'] = 1;//是否已读 1未读 2已读
        Notice::insertGetId($send_add_notice);
        // 发送个推消息
        Notice::sendGetuiPush($send_add_notice);
        $this->success('修改完成',$params);
    }

    //更新课程详情
    public function up_class_detail(){
        $params = $this->request->param();
        if(!isset($params['id'])||!$params['id']){
            $this->error('课程id必传');
        }
        $user = $this->auth->getUser();
        if(!$user){
            $this->error('未获取到用户信息');
        }
        if($user['identity_type'] != '校方'){
            $this->error('当前身份不可修改课程信息');
        }
        $class = TeacherClass::where(['id'=>$params['id']])->with(['dtls'])->find();
        if(isset($params['address_id'])&&$params['address_id']){
            $address_id = $params['address_id'];
        }
        if($class['status']==3){
            $this->error('课程已中止，无法修改');
        }
        $identity_info = \app\admin\model\IdentityInfo::where(['user_id'=>$class['teacher_id'],'identity_type'=>'教师'])->with(['clubDtlS'])->find();
        if(!$identity_info){
            $this->error('教师不存在');
        }
        $td = \app\admin\model\TeacherDetail::where(['id'=>$class['teacher_detail_id']])->find();
        if(isset($td['course_duration'])&&$td['course_duration']){
            //当教师课程配置了课程时间 则赋值课程时间
            $duration = $td['course_duration'];
        }else{
            //如果没有配置，则取公共课程时间
            $defaultDuration = Config::get('course.default_course_duration', '');
            $duration = $defaultDuration;
        }
        $time = explode('-',$identity_info['appointment_time']);
        $week_pd = date('N');
        $date = date('H:i:s');
        //确认是周末才可以改
        if($week_pd == 7&&$date>'23:00:00'){
            $this->error('周日23点之后为更新进度状态时间，不可修改状态，请于0点后尝试');
        }
        if(!isset($params['start_date'])||!$params['start_date']){
            $params['start_date'] = $class['start_date'];
        }
        $ts = TeacherSubscribe::where(['teacher_id'=>$class['teacher_id']])->where('1=1 and (class_id = 0 or class_id='.$params['id'].')')->select();
        $week_arr = [];
        foreach ($ts as $k=>$v){
            $week_arr[] = $v['week'];
        }
//        $week = explode(',',$identity_info['appointment_time_week']);
        $identity_info_model = new \app\admin\model\IdentityInfo();
        $week_list_name = $identity_info_model->getWeekNameList();
//        $week_arr = [];
//        foreach ($week as $k=>$v){
//            $key = isset($week_list_name[$v]) ? $week_list_name[$v] : '';
//            $week_arr[$k] = $key;
//        }

        $dtl_status = [];
        $old_week = [];
        $time_start = '';
        if($class['period_set'] == 1) {
            foreach ($class['dtls'] as $k=>$v){
                $dtl_status[$week_list_name[$v['week_date']]] = $v['status'];
                $old_week[] = $week_list_name[$v['week_date']];
                $time_start = $v['time_start'];
            }
        }
        $jian_num = 0;
        $jia_num = 0;
        $all_class_num = 0;
        $is_kc = 0;
        if(isset($params['dtl'])&&$params['dtl']){
            if($class['period_set'] == 2) {
                //短期
                $this->error('短期不可修改课程安排');
            }
            if(is_array($params['dtl'])){
                $dtl = $params['dtl'];
            }else{
                //php中参数有双引号 会自动转换
                $params['dtl'] = htmlspecialchars_decode($params['dtl'], ENT_QUOTES);
                $dtl = json_decode($params['dtl'],true);
            }
            $dtl_arr = [];
            $arr_week = [];
            foreach ($dtl as $k=>$v){
                if(!isset($params['class_start_time'])||!$params['class_start_time']){
                    $params['class_start_time'] = $v['time_start'] = $time_start;
                }
                if(!isset($v['week_date'])||!$v['week_date']){
                    $this->error('日期或周必传');
                }
                $arr_week[$k] = $v['week_date'];
//                if(!isset($v['time_start'])||!$v['time_start']){
//                    $this->error('开始时间必传');
//                }
                if(!isset($v['class_num'])||!$v['class_num']){
                    $this->error('课时必传');
                }
                if(!isset($v['status'])||!$v['status']){
                    $this->error('状态必传');
                }


                if(isset($dtl_status[$v['week_date']])&&$dtl_status[$v['week_date']]){
                    if($dtl_status[$v['week_date']] == 2 &&$v['status'] == 1){
                        //修改状态为未开始 进度减1
                        $jian_num = precisionRestore($jian_num,$v['class_num'],'减法');
                    }
                    if($dtl_status[$v['week_date']] == 1 &&$v['status'] == 2){
                        //修改状态为已完成 进度加1
                        $jia_num = precisionRestore($jia_num,$v['class_num'],'加法');
                    }
                }
                $weekday = $v['week_date'];//长期默认周 传过来的是数字
                //判断日期是否在可约范围内，判断上课时间，判断课时
                if($class['period_set'] == 2){
                    //短期
                    $inputDate = $v['week_date'];

                    $weekday = date('N', strtotime($inputDate));
                }

                if (!in_array($weekday, $week_arr)) {
                    $this->error('周'.TeacherClassDtl::numberToChinese($weekday).'不在可约时间');
                }
                if($v['class_num']>6){
                    $this->error('单次上课最大6课时');
                }
                if(isset($time[0])&&$time[0]&&isset($time[1])&&$time[1]){
                    $add_time = precisionRestore($v['class_num'],$duration,'乘法');
                    $end_time = $this->safeTimeAdd($params['class_start_time'],$add_time);
                    if(!$end_time){
                        $this->error('课程开始时间加上课时不可跨天');
                    }
                    $result = $this->isTimeBetween($params['class_start_time'], $time[0], $time[1]);
                    if($result == false){
                        $this->error('课程开始时间不在服务时间内');
                    }
                    $result = $this->isTimeBetween($end_time, $time[0], $time[1]);
                    if($result == false){
                        $this->error('课程结束时间不在服务时间内');
                    }
                }
                $dtl_arr[$k]['teacher_class_id'] = $params['id'];//课程id
                if($class['period_set'] == 1){
                    $week_date = '周'.TeacherClassDtl::numberToChinese($weekday);
                }else{
                    $week_date = $v['week_date'];
                }

                $dtl_arr[$k]['week_date'] = $week_date;//日/周
                $dtl_arr[$k]['time_start'] = $params['class_start_time'];//开始时间
                $dtl_arr[$k]['class_num'] = $v['class_num'];//课时
                $dtl_arr[$k]['cycle'] = $class['period_set'];//周期 1每周 2日期
                $dtl_arr[$k]['status'] = $v['status'];//状态 1未开始 2已完成
                $all_class_num = precisionRestore($v['class_num'],$all_class_num,'加法');

                if($class['period_set'] == 2){
                    $dtl_arr[$k]['date'] = $v['class_date'];
                }else{
                    $dtl_arr[$k]['date'] = self::calculateTargetDate($params['start_date'],$v['class_date']);
                }

            }
            $hasDuplicate = count($arr_week) !== count(array_unique($arr_week));
            if($hasDuplicate == true){
                $this->error('不可设置相同的周');
            }
            $count = TeacherSubscribe::where(['teacher_id'=>$class['teacher_id']])->where('class_id >0 and class_id !='.$class['id'])->whereIn('week',array_unique($arr_week))->count();
            if($count>0){
                $this->error('存在不可配置的可约时间');
            }
            $sub = TeacherSubscribe::up_class_subscribe(array_unique($arr_week),$class['teacher_id'],$params['id'],$old_week);
            if($sub['code'] == 0){
                $this->error($sub['msg']);
            }
            TeacherClassDtl::where(['teacher_class_id'=>$params['id']])->delete();
            if(count($dtl_arr)){
                TeacherClassDtl::insertAll($dtl_arr);
            }
            $class_num_bg = precisionRestore($jia_num,$jian_num,'减法');
            $completed_class_num = precisionRestore($class['completed_class_num'],$class_num_bg,'加法');
            $class_num_all = (int)$class['class_num_all'];
            $all_class_num = (int)$all_class_num;
            if($all_class_num&&$class_num_all){
                $class_period = ceil($class_num_all / $all_class_num);
            }else{
                $class_period = '暂无计划';
            }
            TeacherClass::where(['id'=>$params['id']])->update(['class_period'=>$class_period.'周','start_date'=>$params['start_date'],'completed_class_num'=>$completed_class_num]);
            //完成进度
            TeacherClassDtl::jd_send_notice($params['id']);
            //发送通知 告知教师 修改了课程安排
            $is_kc = 1;
        }
        $is_dz = 0;
        if(isset($address_id)&&$address_id){
            if($class['address_id']!=$address_id){
                //发送通知 告知教师 修改了上课地点
                $is_dz = 1;
                TeacherClass::where(['id'=>$params['id']])->update(['address_id'=>$address_id]);
            }
        }
        $school_info = \app\admin\model\IdentityInfo::where(['user_id'=>$class['user_id'],'identity_type'=>'校方'])->find();
        $content = '';
        if($is_kc == 1){
            $content = $school_info['school'].'-'.$school_info['name'].' 修改了您的课程安排，请前往课程表查看';
        }
        if($is_dz == 1){
            $content = $school_info['school'].'-'.$school_info['name'].' 修改了您的上课地址，请前往课程表查看';
        }
        if($is_kc == 1 && $is_dz == 1){
            $content = $school_info['school'].'-'.$school_info['name'].' 修改了您的课程安排和上课地址，请前往课程表查看';
        }
        //给教师发通知 告知有人买课了
        $send_add_notice = [];
        $send_add_notice['title'] = '课程安排变更';//标题
        $send_add_notice['content'] = $content;//内容
        $send_add_notice['need_confirm'] = 2;//是否需要确认 1是 2否
        $send_add_notice['jump'] = '课程详情';//跳转地址
        $send_add_notice['teacher_class_id'] = $params['id'];//课程id
        $send_add_notice['teacher_class_dtl_id'] = 0;//课程安排id
        $send_add_notice['send_user_id'] = $class['user_id'];//发送人id
        $send_add_notice['get_user_id'] = $class['teacher_id'];//接收人id
        $send_add_notice['identity_type'] = '教师';//接收人身份
        $send_add_notice['addtime'] = date('Y-m-d H:i:s');//添加时间
        $send_add_notice['is_read'] = 1;//是否已读 1未读 2已读
        Notice::insertGetId($send_add_notice);
        // 发送个推消息
        Notice::sendGetuiPush($send_add_notice);
        $this->success('修改完成',$params);
    }

    function calculateTargetDate($start_date, $target_weekday) {
        // 验证开始日期格式
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $start_date)) {
            return "错误：开始日期格式不正确，请使用YYYY-MM-DD格式";
        }

        // 定义星期映射关系
        $weekday_map = [
            '周一' => 0, '星期二' => 1, '周二' => 1,
            '周三' => 2, '星期三' => 2,
            '周四' => 3, '星期四' => 3,
            '周五' => 4, '星期五' => 4,
            '周六' => 5, '星期六' => 5,
            '周日' => 6, '星期日' => 6, '星期天' => 6,'周天' => 6,
        ];

        // 检查目标星期参数是否有效
        if (!isset($weekday_map[$target_weekday])) {
            return "错误：无效的星期参数，请使用如'周一'、'周二'等格式";
        }

        $target_weekday_num = $weekday_map[$target_weekday];

        // 获取开始日期的星期几（0为周日，1-6为周一到周六）
        $start_weekday = date('w', strtotime($start_date));
        // 将周日的0转换为6，统一为0-5表示周一到周六，6表示周日
        if ($start_weekday == 0) {
            $start_weekday = 6;
        } else {
            $start_weekday = $start_weekday - 1;
        }
        // 计算天数差
        $day_diff = $target_weekday_num - $start_weekday;

        // 如果目标星期在开始日期之前，需要加上7天来获取下一周的日期
        if ($day_diff < 0) {
            $day_diff += 7;
        }
        // 计算目标日期
        $target_date = date('Y-m-d', strtotime($start_date . " +{$day_diff} days"));

        return $target_date;
    }
    //删除课程(隐藏)
    public function del_class(){
        $params = $this->request->param();
        if(!isset($params['id'])||!$params['id']){
            $this->error('课程id必传');
        }
        $user = $this->auth->getUser();
        if(!$user){
            $this->error('未获取到用户信息');
        }
        $up = 0;
        if($user['identity_type'] == '校方'){
            $class = TeacherClass::where(['user_id'=>$user['id'],'id'=>$params['id']])->find();
            if(!$class){
                $this->error('课程不存在');
            }
            if($class['status'] == 1){
                $this->error('只能删除已完成或者已中止的订单');
            }
            $up = TeacherClass::where(['user_id'=>$user['id'],'id'=>$params['id']])->update(['is_s_del'=>1]);
        }
        if($user['identity_type'] == '教师'){
            $class = TeacherClass::where(['teacher_id'=>$user['id'],'id'=>$params['id']])->find();
            if(!$class){
                $this->error('课程不存在');
            }
            if($class['status'] == 1){
                $this->error('只能删除已完成或者已中止的订单');
            }
            $up = TeacherClass::where(['teacher_id'=>$user['id'],'id'=>$params['id']])->update(['is_t_del'=>1]);
        }
        $this->success('修改完成',$up);
    }

    //取消课程(中止)
    public function stop_class(){
        $params = $this->request->param();
        if(!isset($params['id'])||!$params['id']){
            $this->error('课程id必传');
        }
        $user = $this->auth->getUser();
        if(!$user){
            $this->error('未获取到用户信息');
        }

        if($user['identity_type'] != '校方'){
            $this->error('只能由校方取消');
        }
        if(!isset($params['del_reason'])||!$params['del_reason']){
            $this->error('删除未完成课程需要填入理由');
        }
        $class = TeacherClass::where(['user_id'=>$user['id'],'id'=>$params['id']])->find();
        if(!$class){
            $this->error('课程不存在');
        }

        if($class['status'] == 1){
            $identity_info = \app\admin\model\IdentityInfo::where(['identity_type'=>'校方','user_id'=>$user['id']])->find();
            $name = isset($identity_info['name']) ? $identity_info['name'] : '';
            $school = isset($identity_info['school']) ? $identity_info['school'] : '';
            $send_add_notice = [];
            $send_add_notice['title'] = '课程中止通知';//标题
            $send_add_notice['content'] = '您的课程已中止,请注意查看！中止人：'.$name.' '.$school;//内容
            $send_add_notice['need_confirm'] = 2;//是否需要确认 1是 2否
            $send_add_notice['jump'] = '课程详情';//跳转地址
            $send_add_notice['teacher_class_id'] = $params['id'];//课程id
            $send_add_notice['teacher_class_dtl_id'] = 0;//课程安排id
            $send_add_notice['send_user_id'] = $user['id'];//发送人id
            $send_add_notice['get_user_id'] = $class['teacher_id'];//接收人id
            $send_add_notice['identity_type'] = '教师';//接收人身份
            $send_add_notice['addtime'] = date('Y-m-d H:i:s');//添加时间
            $send_add_notice['is_read'] = 1;//是否已读 1未读 2已读
            Notice::insertGetId($send_add_notice);
            // 发送个推消息
            Notice::sendGetuiPush($send_add_notice);
            $up = TeacherClass::where(['user_id'=>$user['id'],'id'=>$params['id']])->update(['del_reason'=>$params['del_reason'],'status'=>3]);
            TeacherSubscribe::class_success_up($params['id'],$class['teacher_id']);
            $this->success('取消成功',$up);
        }else{
            $this->error('只能取消未完成课程');
        }
    }

    //取消原因下拉
    public function get_stop_class_pull(){
        $stop = StopClassReason::where(['status'=>1])->field('name')->select();
        $this->success('取消原因',$stop);
    }

    //评分
    public function add_score(){
        $params = $this->request->param();
        if(!isset($params['id'])||!$params['id']){
            $this->error('课程id必传');
        }
        $user = $this->auth->getUser();
        if(!$user){
            $this->error('未获取到用户信息');
        }
        if(!isset($params['score'])||!$params['score']){
            $this->error('评分必传,最低一分');
        }

        $find = TeacherClass::where(['id'=>$params['id'],'user_id'=>$user['id']])->find();
        if(!$find){
            $this->error('不可评分的订单');
        }
        if($find['score'] != ''){
            $this->error('已评分不可修改');
        }
        $find->save(['score'=>$params['score']]);
        $tc = TeacherClass::where(['teacher_id'=>$find['teacher_id']])->select();
        $all_score = 0;
        $all_count = 0;
        foreach ($tc as $k=>$v){
            if($v['score']){
                $all_score = precisionRestore($all_score,$v['score'],'加法');
                $all_count++;
            }
        }
        if(!$all_score||!$all_count){
            $user_score = '';
        }else{
            $user_score = precisionRestore($all_score,$all_count,'除法');
        }
        if($user_score){
            $user_score = round($user_score,1);
        }
        \app\admin\model\IdentityInfo::where(['user_id'=>$find['teacher_id']])->update(['user_score'=>$user_score]);

        $this->success('评分完成',true);
    }



    function isTimeBetween($checkTime, $startTime, $endTime) {
        $checkTime = trim($checkTime);
        $startTime = trim($startTime);
        $endTime = trim($endTime);
        $check = \DateTime::createFromFormat('H:i', $checkTime);
        $start = \DateTime::createFromFormat('H:i', $startTime);
        $end = \DateTime::createFromFormat('H:i', $endTime);

        if ($check >= $start && $check <= $end) {
            return true;
        }
        return false;
    }

    /**
     * 安全时间加法（禁止跨天）
     * @param string $time 输入时间（格式: H:i）
     * @param int $minutes 要添加的分钟数（支持负数）
     * @return string|false 成功返回时间，失败返回false
     */
    function safeTimeAdd($time, $minutes) {
        $time = trim($time);
        $dt = \DateTime::createFromFormat('H:i', $time);
        if (!$dt) return false;

        $dt->add(new \DateInterval('PT' . abs($minutes) . 'M'));
        if ($minutes < 0) {
            $dt->sub(new \DateInterval('PT' . abs($minutes) . 'M'));
        }

        $originalDay = \DateTime::createFromFormat('H:i', $time)->format('Y-m-d');
        return ($dt->format('Y-m-d') === $originalDay)
            ? $dt->format('H:i')
            : false;
    }

    //请假
    public function vacation(){
        $params = $this->request->param();
        if(!isset($params['id'])||!$params['id']){
            $this->error('课程id必传');
        }
        $user = $this->auth->getUser();
        if(!$user){
            $this->error('未获取到用户信息');
        }
        if(!isset($params['start_time'])||!$params['start_time']){
            $this->error('请假时间必传');
        }
        $tc = TeacherClass::where(['id'=>$params['id']])->find();
        if($tc['status'] != 1){
            $this->error('课程已完成或已中止不可请假');
        }
        $save = [];
        $save['class_id'] = $params['id'];
        $save['user_id'] = $user['id'];
        $save['start_time'] = $params['start_time'];
        if(isset($params['make_up_classes_time'])&&$params['make_up_classes_time']){
            $save['make_up_classes_time'] = $params['make_up_classes_time'];
        }
        if(isset($params['reason'])&&$params['reason']){
            $save['reason'] = $params['reason'];
        }

        $save['addtime'] = date('Y-m-d H:i:s');
        $save['status'] = 1;
        $ask_id = AskForLeave::insertGetId($save);

        $teacher_info = \app\admin\model\IdentityInfo::where(['user_id'=>$user['id'],'identity_type'=>'教师'])->find();

        $notice = [];
        $notice['title'] = '教师请假审批';//标题
        $content = $teacher_info['name'].'向您申请请假';//内容
        if(isset($params['reason'])&&$params['reason']){
            $content .= ',请假理由是:"'.$params['reason'].'"';//内容
        }
        if(isset($params['make_up_classes_time'])&&$params['make_up_classes_time']){
            $content .= ',补课时间为: '.$params['make_up_classes_time'].' ';
        }
        $content .= ',请审批！';
        $notice['content'] = $content;//内容
        $notice['need_confirm'] = 1;//是否需要确认 1是 2否
        $notice['jump'] = '课程详情请假';//跳转地址
        $notice['teacher_class_id'] = $params['id'];//课程id
        $notice['teacher_class_dtl_id'] = 0;//课程安排id
        $notice['send_user_id'] = $user['id'];//发送人id

        $class_find = TeacherClass::where(['id'=>$params['id']])->find();

        $notice['get_user_id'] = $class_find['user_id'];//接收人id
        $notice['identity_type'] = '校方';//接收人身份
        $notice['addtime'] = date('Y-m-d H:i:s');//添加时间
        $notice['is_read'] = 1;//是否已读 1未读 2已读
        $notice['sf_id'] = $ask_id;//三方id
        Notice::insertGetId($notice);
        // 发送个推消息
        Notice::sendGetuiPush($notice);
        $this->success('申请已提交',true);
    }

    //打卡
    public function clock_in(){
        $params = $this->request->param();
        if(!isset($params['id'])||!$params['id']){
            $this->error('课程id必传');
        }
        $user = $this->auth->getUser();
        if(!$user){
            $this->error('未获取到用户信息');
        }
        if(!isset($params['img'])||!$params['img']){
            $this->error('图片必传');
        }
        if(!isset($params['remark'])||!$params['remark']){
            $params['remark'] = '';
        }

        $dtls = TeacherClassDtl::where(['teacher_class_id'=>$params['id']])->select();
        $clock_in = 0;
        foreach ($dtls as $k=>$v){
            $subStr = "周";
            if (strstr($v['week_date'], $subStr)) {
                $start_time = getWeekDay(date('Y-m-d H:i:s'));
                if($v['week_date'] == $start_time){
                    //需要打卡
                    $clock_in++;
                }
            }else{
                $date_class = date('Y-m-d',strtotime($v['week_date']));
                if($date_class == date('Y-m-d')){
                    //需要打卡
                    $clock_in++;
                }
            }
        }

        $afl = AskForLeave::where(['class_id'=>$params['id'],'status'=>2])->select();

        foreach ($afl as $k=>$v){
            $date = date('Y-m-d',strtotime($v['make_up_classes_time']));
            $is_within = dateWithinThisWeek($date);
            if($is_within){
                if($date == date('Y-m-d')){
                    //需要打卡
                    $clock_in++;
                }
            }
        }
        //减去已打卡的次数
        $ci_count = ClockIn::where(['class_id'=>$params['id'],'date'=>date('Y-m-d'),'is_sk'=>1])->count();
        $ci_new = ClockIn::where(['class_id'=>$params['id'],'date'=>date('Y-m-d'),'is_sk'=>1])->order('id','desc')->find();
        if(isset($ci_new['is_sk'])&&$ci_new['is_sk']==1){
            //如果上次是上课打卡，那么这次就是下课打卡，不需要判断打卡次数
            $add = [];
            $add['user_id'] = $user['id'];//打卡用户id
            $add['class_id'] = $params['id'];//课程id
            $add['date'] = date('Y-m-d');//打卡日期
            $add['img'] = $params['img'];//打卡图片
            $add['remark'] = $params['remark'];//打卡备注
            $add['addtime'] = date('Y-m-d H:i:s');//添加时间
            $add['is_sk'] = 2;//下课打卡
            ClockIn::insertGetId($add);
        }else{
            $clock_in = precisionRestore($clock_in,$ci_count,'减法');
            if($clock_in<=0){
                $this->error('今日打卡次数已满');
            }
            $add = [];
            $add['user_id'] = $user['id'];//打卡用户id
            $add['class_id'] = $params['id'];//课程id
            $add['date'] = date('Y-m-d');//打卡日期
            $add['img'] = $params['img'];//打卡图片
            $add['remark'] = $params['remark'];//打卡备注
            $add['addtime'] = date('Y-m-d H:i:s');//添加时间
            $add['is_sk'] = 1;//上课打卡
            ClockIn::insertGetId($add);
        }


        $this->success('打卡成功',true);

    }

    //课程报表
    public function class_report()
    {
        $user = $this->auth->getUser();
        if (!$user) {
            $this->error('未获取到用户信息');
        }

        if ($user['identity_type'] != '校方') {
            $this->error('只有校方可以生成报表');
        }
        $class = TeacherClass::where(['user_id' => $user['id']])->with(['teachers', 'address'])->order('id', 'desc')->select();
        $arr = [];
        foreach ($class as $k => $v) {
            $arr[$k]['teacher_name'] = isset($v['teachers']['nickname']) ? $v['teachers']['nickname'] : '';//教师名称
            $arr[$k]['club_two_name'] = $v['club_two_name'];//社团名
            $arr[$k]['completed_class'] = $v['completed_class_num'] . '/' . $v['class_num_all'];//课程进度
            $arr[$k]['status'] = '未完成';//订单状态
            switch ($v['status']) {
                case 1:
                    $arr[$k]['status'] = '未完成';
                    break;
                case 2:
                    $arr[$k]['status'] = '已完成';
                    break;
                case 3:
                    $arr[$k]['status'] = '已中止';
                    break;
            }
            $arr[$k]['money'] = $v['money'];//金额
            $order = Order::where(['order_no' => $v['order_no']])->find();
            $arr[$k]['kp_money'] = '';//开票金额
            $arr[$k]['kp_status'] = '未开票';
            $invoice_status = '未开票';
            if ($order) {
                switch ($order['invoice_status']) {
                    case 0:
                        $invoice_status = '未开票';
                        break;
                    case 1:
                        $invoice_status = '开票中';
                        break;
                    case 2:
                        $invoice_status = '已开票';
                        break;
                }
                $arr[$k]['kp_status'] = $invoice_status;//开票状态

                if ($invoice_status == '已开票') {
                    $invoice = Invoice::whereRaw("FIND_IN_SET({$order['id']},order_id) > 0")->where(['status' => 2])->find();
                    $order_id_all = $invoice['order_id'];
                    $order_id_all_arr = explode(',', $order_id_all);
                    if (count($order_id_all_arr) > 1) {
                        $order_all = Order::whereIn('id', $order_id_all_arr)->select();
                        $order_nos = '';
                        foreach ($order_all as $kk => $vv) {
                            if ($kk == 0) {
                                $order_nos .= $vv['order_no'];
                            } else {
                                $a = ',' . $vv['order_no'];
                                $order_nos .= $a;
                            }
                        }
                        $arr[$k]['kp_money'] = '本单为多订单合并开票，单号分别是：' . $order_nos . '.开票总金额是：' . $invoice['money'];
                    } else {
                        $arr[$k]['kp_money'] = '本单开票金额为:' . $invoice['money'];
                    }
                }
            }
            if (isset($v['address']) && $v['address']) {
                $address_name = $v['address']['school'];
                $address_detail = $v['address']['detail'];
                $arr[$k]['address'] = $address_name . ' ' . $address_detail;//上课地点
            } else {
                $arr[$k]['address'] = '';
            }
            $arr[$k]['teacher_phone'] = isset($v['teachers']['mobile']) ? $v['teachers']['mobile'] : '';//教师电话
        }

        // 生成Excel文件
        $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();

        // 设置表头
        $headers = ['教师名称', '社团名', '课程进度', '订单状态', '金额', '开票状态', '开票金额', '上课地点', '教师电话'];
        $col = 1;
        foreach ($headers as $header) {
            $sheet->setCellValueByColumnAndRow($col, 1, $header);
            $col++;
        }
        // 设置表头样式
        $headerStyle = [
            'font' => [
                'bold' => true,
                'size' => 12,
                'color' => ['rgb' => 'FFFFFF']
            ],
            'fill' => [
                'fillType' => Fill::FILL_SOLID,
                'startColor' => ['rgb' => '4472C4']
            ],
            'alignment' => [
                'horizontal' => Alignment::HORIZONTAL_CENTER,
                'vertical' => Alignment::VERTICAL_CENTER
            ],
            'borders' => [
                'allBorders' => [
                    'borderStyle' => Border::BORDER_THIN,
                    'color' => ['rgb' => '000000']
                ]
            ]
        ];
        $lastCol = Coordinate::stringFromColumnIndex(count($headers));
        $sheet->getStyle('A1:' . $lastCol . '1')->applyFromArray($headerStyle);

        // 填充数据
        $row = 2;
        foreach ($arr as $item) {
            $col = 1;
            $sheet->setCellValueByColumnAndRow($col++, $row, $item['teacher_name'] ?? '');
            $sheet->setCellValueByColumnAndRow($col++, $row, $item['club_two_name'] ?? '');
            $sheet->setCellValueByColumnAndRow($col++, $row, $item['completed_class'] ?? '');
            $sheet->setCellValueByColumnAndRow($col++, $row, $item['status'] ?? '');
            $sheet->setCellValueByColumnAndRow($col++, $row, $item['money'] ?? '');
            $sheet->setCellValueByColumnAndRow($col++, $row, $item['kp_status'] ?? '');
            $sheet->setCellValueByColumnAndRow($col++, $row, $item['kp_money'] ?? '');
            $sheet->setCellValueByColumnAndRow($col++, $row, $item['address'] ?? '');
            $sheet->setCellValueByColumnAndRow($col++, $row, $item['teacher_phone'] ?? '');
            $row++;
        }

        // 设置数据样式
        $dataStyle = [
            'borders' => [
                'allBorders' => [
                    'borderStyle' => Border::BORDER_THIN,
                    'color' => ['rgb' => '000000']
                ]
            ],
            'alignment' => [
                'horizontal' => Alignment::HORIZONTAL_LEFT,
                'vertical' => Alignment::VERTICAL_CENTER
            ]
        ];
        if ($row > 2) {
            $lastCol = Coordinate::stringFromColumnIndex(count($headers));
            $sheet->getStyle('A2:' . $lastCol . ($row - 1))->applyFromArray($dataStyle);
        }

        // 设置列宽
        foreach (range(1, count($headers)) as $col) {
            $sheet->getColumnDimensionByColumn($col)->setAutoSize(true);
        }
        // 手动设置部分列宽
        $sheet->getColumnDimensionByColumn(7)->setWidth(40); // 开票金额列
        $sheet->getColumnDimensionByColumn(8)->setWidth(30); // 上课地点列

        // 设置行高
        $sheet->getRowDimension(1)->setRowHeight(25); // 表头行高
        for ($i = 2; $i < $row; $i++) {
            $sheet->getRowDimension($i)->setRowHeight(20); // 数据行高
        }

        // 生成文件名
        $filename = '课程报表_' . date('YmdHis') . '.xlsx';
        $filepath = ROOT_PATH . 'public' . DS . 'uploads' . DS . 'excel' . DS;

        // 确保目录存在
        if (!is_dir($filepath)) {
            mkdir($filepath, 0755, true);
        }

        $fullPath = $filepath . $filename;

        // 保存Excel文件
        $writer = new Xlsx($spreadsheet);
        $writer->save($fullPath);

        // 上传到OSS
        $ossUrl = $this->uploadToOSS($fullPath, $filename);

        // 删除本地临时文件
        if (file_exists($fullPath)) {
            @unlink($fullPath);
        }

        if ($ossUrl) {
            $this->success('课程报表生成成功', [
                'list' => $arr,
                'excel_url' => $ossUrl,
                'filename' => $filename
            ]);
        } else {
            $this->error('Excel文件上传失败');
        }
    }

    /**
     * 上传文件到OSS
     */
    private function uploadToOSS($filePath, $filename)
    {
        try {
            // 获取OSS配置
            $config = get_addon_config('alioss');
            if (!$config) {
                \think\Log::error('OSS配置不存在');
                return false;
            }

            // 创建OSS客户端
            $ossClient = new OssClient($config['accessKeyId'], $config['accessKeySecret'], $config['endpoint']);

            // 生成OSS存储路径
            $ossKey = '/uploads/excel/' . date('Ymd') . '/' . $filename;
            
            \think\Log::info('开始上传文件到OSS: ' . $filePath . ' -> ' . $ossKey);

            // 上传文件到OSS
            $result = $ossClient->uploadFile($config['bucket'], ltrim($ossKey, '/'), $filePath);
            
            if ($result && isset($result['info']['url'])) {
                $ossUrl = $result['info']['url'];
                \think\Log::info('文件上传到OSS成功: ' . $ossUrl);
                return $ossUrl;
            } else {
                \think\Log::error('OSS上传失败，未返回URL');
                return false;
            }

        } catch (OssException $e) {
            \think\Log::error('OSS上传异常: ' . $e->getMessage());
            return false;
        } catch (\Exception $e) {
            \think\Log::error('上传文件到OSS失败: ' . $e->getMessage());
            return false;
        }
    }
}
